package com.jrx.anytxn.transaction.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.entity.PmPartnerInfo;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.PrProductTable;
import com.jrx.anytxn.param.entity.PrShareProfitTable;
import com.jrx.anytxn.param.service.partner.IPartnerShareProfitService;
import com.jrx.anytxn.param.service.partner.IPmPartnerInfoService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.transaction.bean.PartnerGeneralBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.entity.TlPaymentAllocationLog;
import com.jrx.anytxn.transaction.entity.TlPaymentLog;
import com.jrx.anytxn.transaction.mapper.ext.ExtAmLoanAccountInfoMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlDisbursementLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlPaymentAllocationLogMapper;
import com.jrx.anytxn.transaction.mapper.ext.ExtTlPaymentLogMapper;
import com.jrx.anytxn.transaction.service.IPartnerCountService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class PartnerCountServiceImpl implements IPartnerCountService {

    private static final Logger logger = LoggerFactory.getLogger(PartnerCountServiceImpl.class);

    @Autowired
    private IOrganizationTableService organizationTableService;
    @Autowired
    private ISegmentService segmentService;
    @Resource
    private ExtTlDisbursementLogMapper extTlDisbursementLogMapper;
    @Resource
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;
    @Resource
    private ExtTlPaymentLogMapper extTlPaymentLogMapper;
    @Resource
    private ExtTlPaymentAllocationLogMapper extTlPaymentAllocationLogMapper;
    @Autowired
    private IPmPartnerInfoService pmPartnerInfoService;
    @Autowired
    private IPartnerShareProfitService partnerShareProfitService;

    @Override
    public void partnerGeneral(List<PrProductTable> productTableList,String reportingPath, String fileName, String fileType) throws TxnBizException {
        //放款还款数据抽取
        List<String> lists = new ArrayList<>();
        if(CollectionUtils.isEmpty(productTableList)){
            return;
        }

        //获取当前业务日期
        PrOrganizationTable org =
                organizationTableService.findByOrId(productTableList.get(0).getOrganizationId(), productTableList.get(0).getTenantId());

        for(PrProductTable prProductTable : productTableList){
            PartnerGeneralBean bean = buildGeneralBean(prProductTable,org);
            String fileMess = buildFileMes(bean);
            lists.add(fileMess);
        }
        if(lists.size() > 0 ){
            generatingFile(lists,reportingPath,fileName,fileType,org);
        }
    }

    private PartnerGeneralBean buildGeneralBean(PrProductTable prProductTable,PrOrganizationTable org) throws TxnBizException{
        PrShareProfitTable prShareProfitTable = null;
        if(null != prProductTable.getPartnerId()){
            //获取合作伙伴信息
            PmPartnerInfo pmPartnerInfo = pmPartnerInfoService.getByPartnerId(
                    prProductTable.getTenantId(),prProductTable.getPartnerId());

            //获取合作伙伴分润信息
            if(null != pmPartnerInfo && null != pmPartnerInfo.getProfitId()){
                prShareProfitTable = partnerShareProfitService.getByShareProfitId(
                        pmPartnerInfo.getTenantId(),pmPartnerInfo.getProfitId());
            }
        }

        PartnerGeneralBean log = new PartnerGeneralBean();
        log.setProductId(prProductTable.getProductId());
        log.setTenantId(prProductTable.getTenantId());
        log.setOrganizationId(org.getOrganizationId());
        log.setBusinessDate(org.getToday());

        //统计产品当天放款总条数
        int disCount = extTlDisbursementLogMapper.countByProductIdAndSumStatusAndBusinessDate(
                prProductTable.getProductId(),prProductTable.getTenantId(),TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_S,
                org.getToday());
        if(disCount > 0){
            log.setLoanTotalCount(disCount);
            //获取当日产品放款总金额
            BigDecimal loanTotalAmount = extTlDisbursementLogMapper.sumByProductIdAndSumStatusAndBusinessDate(
                    prProductTable.getProductId(),prProductTable.getTenantId(),TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_S,
                    org.getToday());
            if(null==loanTotalAmount){
                log.setLoanTotalAmount(BigDecimal.ZERO);
            }else{
                log.setLoanTotalAmount(loanTotalAmount);
            }
        }else{
            log.setLoanTotalCount(0);
            log.setLoanTotalAmount(BigDecimal.ZERO);
        }

        //统计产品在余额
        BigDecimal balance = extAmLoanAccountInfoMapper.sumPrincipalBalance(
                prProductTable.getTenantId(), prProductTable.getProductId(),
                Arrays.asList(TransBizConstant.ACCOUNT_STATUS_0,TransBizConstant.ACCOUNT_STATUS_1,TransBizConstant.ACCOUNT_STATUS_2));
        if(null == balance){
            log.setCurrBalance(BigDecimal.ZERO);
        }else{
            log.setCurrBalance(balance);
        }

        BigDecimal paymentAmount = BigDecimal.ZERO;//总还款额
        BigDecimal paymentPrincipal = BigDecimal.ZERO;//总还款本金
        BigDecimal paymentInterest = BigDecimal.ZERO;//总还款利息
        BigDecimal paymentInstallmentFee = BigDecimal.ZERO;//总还款分期手续费
        BigDecimal paymentPrepayFee = BigDecimal.ZERO;//总还款提前还款手续费
        BigDecimal paymentPenalty = BigDecimal.ZERO;//总还款罚息
        BigDecimal paymentCompound = BigDecimal.ZERO;//总还款复利
        BigDecimal paymentPreoffFee= BigDecimal.ZERO;//总还款提前结清手续费

        BigDecimal shareAmount = BigDecimal.ZERO;//分润总金额
        BigDecimal shareInterest = BigDecimal.ZERO;//总应分利息
        BigDecimal shareInstallmentFee = BigDecimal.ZERO;//总应分分期手续费
        BigDecimal sharePrepayFee = BigDecimal.ZERO;//总应分提前还款手续费
        BigDecimal sharePenalty = BigDecimal.ZERO;//总应分罚息
        BigDecimal shareCompound = BigDecimal.ZERO;//总应分复利
        BigDecimal sharePreoffFee = BigDecimal.ZERO;//总应分提前结清手续费


        //统计还款总笔数
        int paymentCount = extTlPaymentLogMapper.countByProductIdAndSumStatusAndBusinessDate(
                prProductTable.getProductId(),prProductTable.getTenantId(),TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,
                org.getToday());
        if(paymentCount > 0){
            log.setPaymentCount(paymentCount);
            List<TlPaymentLog> paymentLogList = extTlPaymentLogMapper.selectByProductIdAndBusiDate(
                    prProductTable.getProductId(),prProductTable.getTenantId(),TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,
                    org.getToday());
            for(TlPaymentLog paymentLog : paymentLogList){
                //账单分期，贴息自动扣款 不计算
                if(TransBizConstant.REPAYMENT_TYPE_STAGING.equals(paymentLog.getPaymentType())||
                        TransBizConstant.REPAYMENT_TYPE_WAIVEAUTO.equals(paymentLog.getPaymentType())){
                    continue;
                }

                paymentAmount = paymentAmount.add(paymentLog.getAmount());

                Boolean isShareProfit = checkShareProfit(paymentLog,prShareProfitTable);

                //根据流水号查询 还款分配历史表
                List<TlPaymentAllocationLog> allocationLogs = extTlPaymentAllocationLogMapper.selectBySeqNoAndTenantId(
                        paymentLog.getSeqNo(),paymentLog.getTenantId());
                //计算还款本利费
                for(TlPaymentAllocationLog allocationLog : allocationLogs){
                    if(TransBizConstant.TXN_CODE_INST_PYMT.equals(allocationLog.getTxnCode())){
                        //还款本金
                        paymentPrincipal = paymentPrincipal.add(allocationLog.getPostingAmount());
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_INTR.equals(allocationLog.getTxnCode())){
                        //还款利息
                        paymentInterest = paymentInterest.add(allocationLog.getPostingAmount());
                        //计算利息分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getInterestShareUnit())){
                                shareInterest = shareInterest.add(prShareProfitTable.getInterestShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                                BigDecimal intValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getInterestShareValue());
                                shareInterest = shareInterest.add(intValue);
                            }
                        }
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_FEE.equals(allocationLog.getTxnCode())) {
                        //分期手续费
                        paymentInstallmentFee = paymentInstallmentFee.add(allocationLog.getPostingAmount());
                        //计算分期手续费分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getInstallmentFeeShareUnit())){
                                shareInstallmentFee = shareInstallmentFee.add(prShareProfitTable.getInstallmentFeeShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                                BigDecimal installmentFeeValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getInstallmentFeeShareValue());
                                shareInstallmentFee = shareInstallmentFee.add(installmentFeeValue);
                            }
                        }
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_PREPAY_FEE.equals(allocationLog.getTxnCode())) {
                        //提前还款手续费
                        paymentPrepayFee = paymentPrepayFee.add(allocationLog.getPostingAmount());
                        //计算提前还款手续费分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPrepayFeeShareUnit())){
                                sharePrepayFee = sharePrepayFee.add(prShareProfitTable.getPrepayFeeShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                                BigDecimal prepayFeeValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPrepayFeeShareValue());
                                sharePrepayFee = sharePrepayFee.add(prepayFeeValue);
                            }
                        }
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_PEN_INTR.equals(allocationLog.getTxnCode())) {
                        //罚息
                        paymentPenalty = paymentPenalty.add(allocationLog.getPostingAmount());
                        //计算罚息分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPenaltyShareUnit())){
                                sharePenalty = sharePenalty.add(prShareProfitTable.getPenaltyShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                                BigDecimal penaltyValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPenaltyShareValue());
                                sharePenalty = sharePenalty.add(penaltyValue);
                            }
                        }
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_COM_INTR.equals(allocationLog.getTxnCode())) {
                        //复利
                        paymentCompound = paymentCompound.add(allocationLog.getPostingAmount());
                        //计算复利分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getCompoundShareUnit())){
                                shareCompound = shareCompound.add(prShareProfitTable.getCompoundShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getCompoundShareUnit())){
                                BigDecimal compoundValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getCompoundShareValue());
                                shareCompound = shareCompound.add(compoundValue);
                            }
                        }
                    }else if(TransBizConstant.TXN_CODE_INST_PYMT_PAYOFF_FEE.equals(allocationLog.getTxnCode())) {
                        //提前结清手续费
                        paymentPreoffFee = paymentPreoffFee.add(allocationLog.getPostingAmount());
                        //计算提前结清手续费分润值
                        if(isShareProfit){
                            if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPreoffFeeShareUnit())){
                                sharePreoffFee = sharePreoffFee.add(prShareProfitTable.getPreoffFeeShareValue());
                            }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getPreoffFeeShareUnit())){
                                BigDecimal preoffValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPreoffFeeShareValue());
                                sharePreoffFee = sharePreoffFee.add(preoffValue);
                            }
                        }
                    }
                }
            }

            //总分润金额
            shareAmount = shareInterest.add(shareInstallmentFee).add(sharePrepayFee).add(sharePenalty).add(shareCompound).add(sharePreoffFee);
        }else{
            log.setPaymentCount(0);
        }

        log.setPaymentAmount(paymentAmount);
        log.setPaymentPrincipal(paymentPrincipal);
        log.setPaymentInterest(paymentInterest);
        log.setPaymentInstallmentFee(paymentInstallmentFee);
        log.setPaymentPrepayFee(paymentPrepayFee);
        log.setPaymentPenalty(paymentPenalty);
        log.setPaymentCompound(paymentCompound);
        log.setPaymentPreoffFee(paymentPreoffFee);
        log.setShareAmount(shareAmount);
        log.setShareInterest(shareInterest);
        log.setShareInstallmentFee(shareInstallmentFee);
        log.setSharePrepayFee(sharePrepayFee);
        log.setSharePenalty(sharePenalty);
        log.setShareCompound(shareCompound);
        log.setSharePreoffFee(sharePreoffFee);
        return log;
    }

    private String buildFileMes(PartnerGeneralBean bean){
        StringBuffer sb = new StringBuffer();
        sb.append(bean.getTenantId() + TransBizConstant.separator);
        sb.append(bean.getOrganizationId() + TransBizConstant.separator);
        sb.append(bean.getProductId() + TransBizConstant.separator);
        String busDate = bean.getBusinessDate()==null?"": DateUtils.format(bean.getBusinessDate());
        sb.append(busDate + TransBizConstant.separator);
        sb.append(bean.getLoanTotalCount() + TransBizConstant.separator);
        sb.append(bean.getLoanTotalAmount() + TransBizConstant.separator);
        sb.append(bean.getCurrBalance() + TransBizConstant.separator);
        sb.append(bean.getPaymentCount() + TransBizConstant.separator);
        sb.append(bean.getPaymentAmount() + TransBizConstant.separator);
        sb.append(bean.getPaymentPrincipal() + TransBizConstant.separator);
        sb.append(bean.getPaymentInterest() + TransBizConstant.separator);
        sb.append(bean.getPaymentInstallmentFee() + TransBizConstant.separator);
        sb.append(bean.getPaymentPrepayFee() + TransBizConstant.separator);
        sb.append(bean.getPaymentPenalty() + TransBizConstant.separator);
        sb.append(bean.getPaymentCompound() + TransBizConstant.separator);
        sb.append(bean.getPaymentPreoffFee() + TransBizConstant.separator);
        sb.append(bean.getShareAmount() + TransBizConstant.separator);
        sb.append(bean.getShareInterest() + TransBizConstant.separator);
        sb.append(bean.getShareInstallmentFee() + TransBizConstant.separator);
        sb.append(bean.getSharePrepayFee() + TransBizConstant.separator);
        sb.append(bean.getSharePenalty() + TransBizConstant.separator);
        sb.append(bean.getShareCompound() + TransBizConstant.separator);
        sb.append(bean.getSharePreoffFee());

        return sb.toString();
    }

    private void generatingFile(List<String> messageList, String reportingPath, String fileName, String fileType,PrOrganizationTable org) {
        String today = DateUtils.format(org.getToday(),"yyyyMMdd");

        String filePath = reportingPath + org.getTenantId() + File.separator + today + File.separator;

        String collectionFileName = fileType+ "_" + today + "_" + fileName + ".txt";

        Path reportingFile = Paths.get(filePath + collectionFileName);

        Integer i = 0;
        try(FileWriter bfw = new FileWriter(reportingFile.toFile(),true);
            BufferedWriter writer = new BufferedWriter(bfw,10240)) {
            if(reportingFile.toFile().length() != 0){
                writer.write("\r\n");
            }
            for (String message : messageList) {
                i++;
                if(i == messageList.size()){
                    writer.write(message);
                }else{
                    writer.write(message + "\r\n");
                }
            }
            writer.flush();
        } catch (IOException e) {
            logger.error("统计文件生成异常，异常信息：",e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 检查是否需要分润
     * @param paymentLog
     * @param prShareProfitTable
     */
    private Boolean checkShareProfit(TlPaymentLog paymentLog,PrShareProfitTable prShareProfitTable){
        Boolean isShareProfit = true;

        if(null == prShareProfitTable){
            isShareProfit = false;
            return isShareProfit;
        }

        if(TransBizConstant.REPAYMENT_TYPE_CMPS.equals(paymentLog.getPaymentType())||
            TransBizConstant.REPAYMENT_TYPE_CRT.equals(paymentLog.getPaymentType())){
            //代偿回购无需分润
            isShareProfit = false;
            return isShareProfit;
        }

        if(TransBizConstant.NO_FLAG.equals(prShareProfitTable.getValidStatus())){
            isShareProfit = false;
            return isShareProfit;
        }

        return isShareProfit;
    }
}
